local select = select
local GUID = UnitGUID"player"
local display = CreateFrame"Frame"
local recorder = CreateFrame"Frame"

recorder:SetScript("OnEvent", function (self, _, ts, event, srcGUID, ...)
	if srcGUID ~= GUID then return end
	if event == "SWING_DAMAGE" then
		return display:AddDamage(ts, select(6, ...))
	end
	if event == "RANGE_DAMAGE" or event == "SPELL_DAMAGE" or event == "SPELL_PERIODIC_DAMAGE" then
		return display:AddDamage(ts, select(9, ...))
	end
end)

display.immediate_real_damage = 0
display.immediate_absolute_damage = 0
display.combat_real_damage = 0
display.combat_absolute_damage = 0
display.max_imm_real_damage = 0
display.max_imm_absolute_damage = 0

display.dataobj = LibStub"LibDataBroker-1.1":NewDataObject("JerryDPS", {
	type = "data source",
	value = "-",
	suffix = "DPS",
})

local IMMEDIATE_TIME_AVG = 5
local mt = { __index = function () return 0 end }
display.real_records = setmetatable({}, mt)
display.absolute_records = setmetatable({}, mt)
function display:get_immediate_values(reset)
	local real, absolute = 0, 0
	for i = 1, IMMEDIATE_TIME_AVG do
		real = real + self.real_records[i]
		absolute = absolute + self.absolute_records[i]
	end
	if reset then
		for i = 1, IMMEDIATE_TIME_AVG do
			self.real_records[i] = 0
			self.absolute_records[i] = 0
		end
	end
	return real, absolute
end

display:SetScript("OnEvent", function (self, event, ...)
	local handler = self[event]
	if handler then return handler(self, event, ...) end
end)
if not GUID then
	display:RegisterEvent"PLAYER_LOGIN"
	function display:PLAYER_LOGIN()
		GUID = UnitGUID"player"
	end
end
display:RegisterEvent"PLAYER_REGEN_DISABLED"
function display:PLAYER_REGEN_DISABLED()
	self.first_timestamp = nil
	self.last_timestamp = nil
	self.current_delta = nil
	self.immediate_real_damage = 0
	self.immediate_absolute_damage = 0
	self.combat_real_damage = 0
	self.combat_absolute_damage = 0
	self.max_imm_real_damage = 0
	self.max_imm_absolute_damage = 0
	recorder:RegisterEvent"COMBAT_LOG_EVENT_UNFILTERED"
end

display:RegisterEvent"PLAYER_REGEN_ENABLED"
function display:PLAYER_REGEN_ENABLED()
	recorder:UnregisterEvent"COMBAT_LOG_EVENT_UNFILTERED"
	if not self.last_timestamp then return end
	local r, a = self:get_immediate_values(true)
	self.combat_real_damage = self.combat_real_damage + r
	self.combat_absolute_damage = self.combat_absolute_damage + a
	local delta = self.last_timestamp - self.first_timestamp
	display:Update(self.combat_real_damage / delta, self.combat_absolute_damage / delta)
end

local math_floor = math.floor
local math_mod = math.fmod
function display:AddDamage(timestamp, amount, overkill, school, resisted, blocked, absorbed)
	local first_timestamp = self.first_timestamp
	if not first_timestamp then
		first_timestamp = timestamp
		self.first_timestamp = timestamp
	end
	self.last_timestamp = timestamp
	local delta = timestamp - first_timestamp
	local current_delta = math_floor(delta)

	local real_damage = amount - (overkill or 0)
	local absolute_damage = amount + (resisted or 0) + (blocked or 0) + (absorbed or 0)

	local immediate_real_damage = self.immediate_real_damage + real_damage
	local immediate_absolute_damage = self.immediate_absolute_damage + absolute_damage

	if current_delta ~= self.current_delta then
		-- update immediate DPS
		local index = math_mod(current_delta, IMMEDIATE_TIME_AVG) + 1
		self.combat_real_damage = self.combat_real_damage + self.real_records[index]
		self.combat_absolute_damage = self.combat_absolute_damage + self.absolute_records[index]
		self.real_records[index] = immediate_real_damage
		self.absolute_records[index] = immediate_absolute_damage

		local real, absolute = self:get_immediate_values()
		real = real / IMMEDIATE_TIME_AVG
		absolute = absolute / IMMEDIATE_TIME_AVG
		if real > self.max_imm_real_damage then
			self.max_imm_real_damage = immediate_real_damage
		end
		if absolute > self.max_imm_absolute_damage then
			self.max_imm_absolute_damage = immediate_absolute_damage
		end
		self.immediate_real_damage, self.immediate_absolute_damage = 0, 0
		display:Update(real, absolute)
	else
		self.immediate_real_damage, self.immediate_absolute_damage = real_damage, absolute_damage
	end
end

function display:Update(real, absolute)
	-- print('dps', real, absolute)
	self.dataobj.value = ("%.1f"):format(real)
end

function display.dataobj.OnTooltipShow(tooltip)
	
	tooltip:AddLine"Dégats"
	tooltip:AddDoubleLine("Immédiat", string.format("%.1f / %.1f", display.immediate_real_damage, display.immediate_absolute_damage), 1, 1, 1)
	tooltip:AddDoubleLine("Combat", string.format("%.1f / %.1f", display.combat_real_damage, display.combat_real_damage), 1, 1, 1)
	tooltip:AddDoubleLine("Max", string.format("%.1f / %.1f", display.max_imm_real_damage, display.max_imm_absolute_damage), 1, 1, 1)
	if display.first_timestamp then
		tooltip:AddDoubleLine("Durée", string.format("%.1f", display.last_timestamp - display.first_timestamp), 1, 1, 1)
	end
	tooltip:Show()
end




